package com.haoxin.ai_course.modules.course.biz;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.haoxin.ai_course.common.utils.CountTool;
import com.haoxin.ai_course.common.utils.HttpJsonResult;
import com.haoxin.ai_course.modules.course.entity.AcCourse;
import com.haoxin.ai_course.modules.course.entity.AcCourseNode;
import com.haoxin.ai_course.modules.course.entity.AcCourseUser;
import com.haoxin.ai_course.modules.course.entity.AcNodeUser;
import com.haoxin.ai_course.modules.course.entity.AcStatisticsCourse;
import com.haoxin.ai_course.modules.course.entity.AcStatisticsCourseDetail;
import com.haoxin.ai_course.modules.course.entity.AcStatisticsUser;
import com.haoxin.ai_course.modules.course.entity.PO.AcCourseUserPO;
import com.haoxin.ai_course.modules.course.entity.VO.AcCourseUserVO;
import com.haoxin.ai_course.modules.course.service.AcCourseNodeService;
import com.haoxin.ai_course.modules.course.service.AcCourseService;
import com.haoxin.ai_course.modules.course.service.AcCourseUserService;
import com.haoxin.ai_course.modules.course.service.AcNodeUserService;
import com.haoxin.ai_course.modules.course.service.AcScoreService;
import com.haoxin.ai_course.modules.course.service.AcStatisticsCourseDetailService;
import com.haoxin.ai_course.modules.course.service.AcStatisticsCourseService;
import com.haoxin.ai_course.modules.course.service.AcStatisticsUserService;
import com.haoxin.ai_course.modules.course.service.AcTopicAnswerResultService;
import com.haoxin.ai_course.modules.sys.entity.SysUser;

import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;

/**
 * 答题结果表
 * 
 * @author xingxiangguo
 * @email bugcn@qq.com
 * @date 2022-06-06 09:44:49
 */
@Slf4j
@Component
public class AcCourseUserBusiness {
	@Autowired
	MapperFacade mapperFacade;
	@Autowired
	AcCourseUserService acCourseUserService;
	@Autowired
	AcCourseService acCourseService;
	@Autowired
	AcStatisticsUserService acStatisticsUserService;
	@Autowired
	AcScoreService acScoreService;
	@Autowired
	AcStatisticsCourseService acStatisticsCourseService;
	@Autowired
	AcTopicAnswerResultService acTopicAnswerResultService;
	@Autowired
	AcStatisticsCourseDetailService acStatisticsCourseDetailService;
	@Autowired
	AcNodeUserService acNodeUserService;

	@Autowired
	private AcCourseNodeService acCourseNodeService;
	@Transactional
	public HttpJsonResult<List<AcCourseUserVO>> fullList(Long userId) {
		log.info("获取所有课程数据fullList，userId:{}",userId);
		HttpJsonResult<List<AcCourseUserVO>> result = new HttpJsonResult<List<AcCourseUserVO>>();
		QueryWrapper<AcCourseUser> qw = new QueryWrapper<AcCourseUser>();
		qw.lambda().eq(AcCourseUser::getUserId, userId);
		List<AcCourseUser> list = acCourseUserService.list(qw);
		if (CollectionUtils.isEmpty(list)&& userId!=null) {
			List<AcCourse> acCourseList = acCourseService.list();
			for (AcCourse acCourse : acCourseList) {
				AcCourseUser acCourseUser = new AcCourseUser();
				acCourseUser.setCourseId(acCourse.getId());
				acCourseUser.setUserId(userId);
				acCourseUser.setCourseName(acCourse.getCourseName());
				acCourseUser.setCourseCode(acCourse.getCourseCode());
				acCourseUser.setStudyTime(0);
				acCourseUser.setStatus(0);
				list.add(acCourseUser);
				QueryWrapper<AcCourseUser> qw1 = new QueryWrapper<AcCourseUser>();
				qw1.lambda().eq(AcCourseUser::getCourseId, acCourse.getId());
				qw1.lambda().eq(AcCourseUser::getUserId, userId);
				Long count = acCourseUserService.count(qw1);
				if(count == 0) {
					acCourseUserService.save(acCourseUser);
				}
			}
		}
		List<AcCourseUserVO> voList = mapperFacade.mapAsList(list, AcCourseUserVO.class);
		log.info("获取所有课程数据fullList,userid:{},数据：{}",userId,voList);
		result.setData(voList);
		return result;
	}
	@Transactional

	public HttpJsonResult<Boolean> changeStatus(AcCourseUserPO acCourseUserPO, SysUser user) {
		log.info("changeStatus修改课程状态,用户：{},参数：{}",user,acCourseUserPO);
		HttpJsonResult<Boolean> result = new HttpJsonResult<Boolean>();
		QueryWrapper<AcCourseUser> qw = new QueryWrapper<AcCourseUser>();
		qw.lambda().eq(AcCourseUser::getUserId, user.getUserId());
		qw.lambda().eq(AcCourseUser::getCourseId, acCourseUserPO.getCourseId());
		AcCourseUser acCourseUser = acCourseUserService.getOne(qw);
		int isStatisticsCourseFinish = 0;
		if (acCourseUser == null) {
			AcCourse acCourse = acCourseService.getById(acCourseUserPO.getCourseId());
			if (acCourse == null||user.getUserId() == null) {
				result.setMsg("课程编号不存在或者用户id为空，请确认！");
				return result;
			}
			acCourseUser = new AcCourseUser();
			acCourseUser.setUserId(user.getUserId());
			acCourseUser.setCourseCode(acCourse.getCourseCode());
			acCourseUser.setCourseName(acCourse.getCourseName());
			acCourseUser.setCreateTime(new Date());
			acCourseUser.setStatus(acCourseUserPO.getStatus());
			acCourseUser.setCourseId(acCourseUserPO.getCourseId());
			acCourseUserService.save(acCourseUser);
		} else {
			if (acCourseUser.getIsStatisticsCourseFinish() == 0) {
				acCourseUser.setIsStatisticsCourseFinish(1);
			} else {
				isStatisticsCourseFinish = 1;
			}
			acCourseUser.setStatus(acCourseUserPO.getStatus());
			acCourseUserService.updateById(acCourseUser);
		}
//		数据统计,统计用户课程的评分信息等
//		updateAcStatisticsCourseUser(acCourseUserPO.getCourseId(), user, acCourseUser.getStatus());
//		统计完课人数
		log.info("changeStatus状态修改完成，判定是否统计课程,用户：{},参数：{}",user,acCourseUserPO);
		if (acCourseUserPO.getStatus() == 1&& isStatisticsCourseFinish == 0 ) {
			log.info("changeStatus统计课程信息,用户：{},参数：{}",user,acCourseUserPO);
//			完课人数递增
//			countCourse(acCourseUserPO.getCourseId(), user.getUserId());
		}

		result.setData(true);
		return result;
	}
//	private void updateAcStatisticsCourseUser(Integer courseId, SysUser user, int status) {
//		QueryWrapper<AcStatisticsUser> qw = new QueryWrapper<AcStatisticsUser>();
//		qw.lambda().eq(AcStatisticsUser::getUserId, user.getUserId());
//		qw.lambda().eq(AcStatisticsUser::getCourseId, courseId);
//		qw.lambda().eq(AcStatisticsUser::getCourseFinish, 0);
//		AcStatisticsUser acStatisticsUser = acStatisticsUserService.getOne(qw);
//		String mobile = user.getMobile();
//		if (mobile == null) {
//			mobile = user.getUsername();
//		}
//		log.info("获取课程统计用户信息修改前:{}", acStatisticsUser);
//		if (acStatisticsUser != null) {
//			acStatisticsUser.setMobile(mobile);
////			是否完课
//			acStatisticsUser.setCourseFinish(status);
//			log.info("获取课程统计用户信息修改后:{}", acStatisticsUser);
//			acStatisticsUserService.updateById(acStatisticsUser);
//		}else {
//			log.error("更新用户统计信息失败，课程尚未学习");
//		}
//	
//	}
//	重新计算中位数时长
	private void countCourseV2(int courseId,Long userId, int studyTime) {
//		统计数据来自用户统计表
//		当用户统计表中重看人数为0的只有一条记录时
//		进入人数=1 完课人数=完课状态为1的人数  首次完课中位数时长= 用户统计表第一条记录的时长 首次完课平均时长=第一条记录的时长，  单课完成率=100 重看人数= 用户统计表中重看次数大于0的数量总和
//		查询用户统计表中 重看次数为0的记录 
		log.info("countCourseV2，课程统计开始：courseId：{},userId:{},studyTime:{}",courseId, userId,  studyTime);
		QueryWrapper<AcStatisticsUser> qw4 = new QueryWrapper<AcStatisticsUser>();
		qw4.lambda().eq(AcStatisticsUser::getCourseId, courseId);
		qw4.lambda().orderByAsc(AcStatisticsUser::getStudayTime);
		List<AcStatisticsUser> singleCourseStatisticsUserList = acStatisticsUserService.list(qw4);
	
		if(CollectionUtils.isEmpty(singleCourseStatisticsUserList)) {
			log.info("countCourseV2，课程统计,用户统计表数据为空");
			return;
		}
//		进入用户列表
		for (AcStatisticsUser acStatisticsUser : singleCourseStatisticsUserList) {
			if( acStatisticsUser.getUserId().longValue() == userId && acStatisticsUser.getRevisitTimes() == 0) {
				acStatisticsUser.setCourseFinish(1);
				acStatisticsUser.setStudayTime(studyTime);
				break;
			}
		}
		List<AcStatisticsUser> enterList =  singleCourseStatisticsUserList.stream().filter(x->x.getRevisitTimes()==0).collect(Collectors.toList());
//		进入人数
		Long enterCount = (long)enterList.size();
//		重看用户列表  
		List<AcStatisticsUser>revisitList = singleCourseStatisticsUserList.stream().filter(x->x.getRevisitTimes()>0).collect(Collectors.toList());
//		重看人数  
		int reviewCount = revisitList.size();
//		完课用户列表
		List<AcStatisticsUser> finishList = singleCourseStatisticsUserList.stream().filter(x->x.getCourseFinish() == 1&&x.getRevisitTimes() == 0).collect(Collectors.toList());
		QueryWrapper<AcStatisticsCourse> qw1 = new QueryWrapper<>();
		qw1.lambda().eq(AcStatisticsCourse::getCourseId, courseId);
		AcStatisticsCourse acStatisticsCourse = acStatisticsCourseService.getOne(qw1);
		if(acStatisticsCourse == null) {
			acStatisticsCourse = new AcStatisticsCourse();
			acStatisticsCourse.setCourseId(courseId);
			acStatisticsCourse.setCourseCode(singleCourseStatisticsUserList.get(0).getCourseCode());
		}
		int  finishCount = finishList.size();
		log.info("countCourseV2，课程统计数据情况：enterCount：{},reviewCount:{},finishCount:{}",enterCount,reviewCount,finishCount);
		List<Integer> times = finishList.stream().map(x -> x.getStudayTime()).collect(Collectors.toList());
		BigDecimal singleCourseFinishRate =  CountTool.countSingleCourseFinishRate (finishCount,enterCount);
		Integer finishCourseMedianTime = CountTool.countMedianTime(times);
		Integer finishCourseAvageTime = CountTool.countAvageTime(times);
		log.info("countCourseV2，课程统计，统计中位数时长，带入数据{},计算的时长:{},",times,finishCourseMedianTime);
		acStatisticsCourse.setFinishCourseMedianTime(finishCourseMedianTime);
		acStatisticsCourse.setFinishCourseAvageTime(finishCourseAvageTime);
		acStatisticsCourse.setSingleCourseFinishRate(singleCourseFinishRate);
		acStatisticsCourse.setFinishCourseCount(finishCount);
		acStatisticsCourse.setEnterCourseCount(enterCount);
		acStatisticsCourse.setReviewCount(reviewCount);
		acStatisticsCourseService.saveOrUpdate(acStatisticsCourse);
//		计算的指标
//		首次完课中位数时长  完课中位时长 x时长  n是总人数   奇数公式：x*(n+1)/2  偶数公式：[x*(n/2)+x(n/2+1)]/2
//		偶数	中位数时长= 中间位置的两个时长相加除以2 减一（因为索引从0开始所以减一）
		
//		中位奇数数时长= 总数+1除以2 减一 索引所在位置的时长
		
//		首次完课平均时长 用户统计表中完课状态为1 的并且 重看人数 revisit_times为0的时长总计  除以 用户统计表中完课状态为1 的并且 重看人数 revisit_times为0 总人数
//		单课完成率 用户统计表中完课状态为1 的并且 重看人数 revisit_times为0 的个数 除以  用户统计表中完课状态为0 的并且 重看人数 revisit_times为0 的个数
//		完课人数 用户统计表中 完课状态为 1 并且 重看人数 revisit_times为0 的个数
//		进入人数 用户统计表中  重看人数 revisit_times 等于0的个数
//		重看人数  用户统计表中 某课程 重看人数 revisit_times 大于0的个数
		
		
	}

	/**
	 * 更新学习时长和增加退出环节人数
	 * 
	 * @param userId
	 * @param courseId
	 * @param nodeId
	 * @param studyTime
	 * @return
	 */
	@Transactional
	public HttpJsonResult<Boolean> updateCourseStudyTime(Long userId, int courseId, int nodeId, int studyTime,
			String mobile,String dataId) {
		HttpJsonResult<Boolean> result = new HttpJsonResult<Boolean>();
		log.info("updateCourseStudyTime 统计时长，入参：userid:{},courseId:{},nodeId:{},studyTime:{},mobile:{}", userId,
				courseId, nodeId, studyTime, mobile);
		int dataCount = acCourseUserService.getDataId(dataId);
		if(dataCount>0) {
			log.info("updateCourseStudyTime 统计时长，重复调用，未参与统计，入参：userid:{},courseId:{},nodeId:{},studyTime:{},mobile:{}", userId, courseId,
					nodeId, studyTime, mobile);
			result.setMsg("统计时长，重复调用，未参与统计");
			result.setData(true);
			result.setCode(0);
			return result;
		}
		try {
			 acCourseUserService.saveDataId("updateCourseStudyTime_"+userId+"_"+dataId);
		} catch (Exception e) {
			e.printStackTrace();
			log.info("updateCourseStudyTime 统计时长 入参：userid:{},courseId:{},nodeId:{},studyTime:{},mobile:{}，插入数据库异常:{}，", userId, courseId,
					nodeId, studyTime, mobile,e.getMessage());
			result.setMsg("统计时长，数据标识插入数据库失败，未参与统计");
			result.setData(true);
			result.setCode(0);
			return result;
		}
		
		QueryWrapper<AcNodeUser> acNodeUserQueryWrapper = new QueryWrapper<AcNodeUser>();
		acNodeUserQueryWrapper.lambda().eq(AcNodeUser::getNodeId, nodeId);
		acNodeUserQueryWrapper.lambda().eq(AcNodeUser::getUserId, userId);
		AcNodeUser acNodeUser = acNodeUserService.getOne(acNodeUserQueryWrapper);
		QueryWrapper<AcCourseUser> acCourseUserqQueryWrapper = new QueryWrapper<AcCourseUser>();
		acCourseUserqQueryWrapper.lambda().eq(AcCourseUser::getUserId, userId);
		acCourseUserqQueryWrapper.lambda().eq(AcCourseUser::getCourseId, courseId);
		AcCourseUser acCourseUser = acCourseUserService.getOne(acCourseUserqQueryWrapper);
		QueryWrapper<AcStatisticsUser> qw = new QueryWrapper<AcStatisticsUser>();
		qw.lambda().eq(AcStatisticsUser::getUserId, userId);
		qw.lambda().eq(AcStatisticsUser::getCourseId, courseId);
		qw.lambda().eq(AcStatisticsUser::getCourseFinish, 0);
		AcStatisticsUser acStatisticsUser = acStatisticsUserService.getOne(qw);
		log.info("updateCourseStudyTime 统计时长，修改用户信息修改前:{}", acStatisticsUser);
		AcCourseNode acCourseNode = acCourseNodeService.getById(nodeId);
//		获取课程的学习状态
		 if(acCourseUser != null && acStatisticsUser !=null) {
			 int time = acStatisticsUser.getStudayTime() == null ? 0 : acStatisticsUser.getStudayTime();
				studyTime = time + studyTime;
				if (StringUtils.isNotBlank(acCourseNode.getNodeName()) && "结束".equals(acCourseNode.getNodeName())) {
					acStatisticsUser.setLastNodeId(nodeId);
					String lastNodeName = "课程编号：" + acCourseNode.getCourseId() + " 环节名称：作业页 ";
					acStatisticsUser.setLastNodeName(lastNodeName);
					acStatisticsUser.setCourseFinish(1);
					if(acStatisticsUser.getRevisitTimes() == 0) {
						countCourseV2(courseId, userId,studyTime);
					}
				} else {
					acStatisticsUser.setLastNodeId(nodeId);
					String lastNodeName = "课程编号：" + acCourseNode.getCourseId() + " 环节编号：" + nodeId + " 环节名称："
							+ acCourseNode.getNodeName() + " 环节内容：" + acCourseNode.getNodeContent();
					acStatisticsUser.setLastNodeName(lastNodeName);
				}
				acStatisticsUser.setStudayTime(studyTime);
				log.info("updateCourseStudyTime方法统计时长，修改用户信息修改后:{}", acStatisticsUser);
				acStatisticsUserService.updateById(acStatisticsUser);
		 }
		

//		重新统计进入课程人数=课程用户表该课程的总人数，完成课程人数=课程用户表course_finish=1的人数，单课完成率=该课完成人数/进入课程人数，
//		完课中位数时长= x时长  n是总人数   奇数公式：x*(n+1)/2  偶数公式：[x*(n/2)+x(n/2+1)]/2   及 完课平均时长 =总时长/进入人数
//		修改环节表，增加退出人数
		QueryWrapper<AcStatisticsCourseDetail> acStatisticsCourseDetailQW = new QueryWrapper<AcStatisticsCourseDetail>();
		acStatisticsCourseDetailQW.lambda().eq(AcStatisticsCourseDetail::getCourseId, courseId);
		acStatisticsCourseDetailQW.lambda().eq(AcStatisticsCourseDetail::getNodeId, nodeId);
		List<AcStatisticsCourseDetail> acStatisticsCourseDetailList = acStatisticsCourseDetailService
				.list(acStatisticsCourseDetailQW);
		if (CollectionUtils.isNotEmpty(acStatisticsCourseDetailList)) {
			for (AcStatisticsCourseDetail acStatisticsCourseDetail : acStatisticsCourseDetailList) {
				if (acStatisticsCourseDetail.getQuitCount() == null) {
					acStatisticsCourseDetail.setQuitCount(1);
				} else {
					if (acNodeUser != null && acNodeUser.getIsQuit() == 0) {
						acNodeUser.setIsQuit(1);
						acStatisticsCourseDetail.setQuitCount(acStatisticsCourseDetail.getQuitCount() + 1);
						acNodeUserService.updateById(acNodeUser);
					}
				}
				acStatisticsCourseDetailService.updateById(acStatisticsCourseDetail);
			}
		}
		result.setData(true);
		return result;
	}
	
	
	/**
	 * 清空表
	truncate table ac_score;
truncate table ac_statistics_answer;
truncate table ac_statistics_article;
truncate table ac_statistics_course;
truncate table ac_statistics_course_detail;
truncate table ac_statistics_user;
truncate table ac_topic_answer_result;
truncate table ac_node_user;
truncate table  ac_course_user;
truncate table ac_data_record;




	 */
	
}
